package com.yitao.cms.utils;

import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.ComparableExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.skipper.base.data.querydsl.PredicateBuilder;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.function.Supplier;

public class PredicateBuilderRealize extends PredicateBuilder {

    private Predicate predicate;

    public PredicateBuilderRealize(Predicate predicate) {
        super(predicate);
    }

    public static PredicateBuilderRealize conjunction() {
        return new PredicateBuilderRealize(ExpressionUtils.eqConst(Expressions.ONE, 1));
    }

    public static PredicateBuilderRealize disjunction() {
        return new PredicateBuilderRealize(ExpressionUtils.eqConst(Expressions.ONE, 0));
    }

    public PredicateBuilderRealize ifNotNullThenOr(Object value, Supplier<Predicate> supplier) {
        return this.ifTrueThenOr(value != null, supplier);
    }

    public PredicateBuilderRealize ifTrueThenOr(Boolean condition, Supplier<Predicate> supplier) {
        return condition != null && condition ? this.or(supplier) : this;
    }

    public PredicateBuilderRealize or(Supplier<Predicate> supplier) {
        Assert.notNull(supplier);
        this.predicate = ExpressionUtils.or(this.predicate, (Predicate)supplier.get());
        return this;
    }

    public PredicateBuilder and(Supplier<Predicate> supplier) {
        Assert.notNull(supplier);
        this.predicate = ExpressionUtils.and(this.predicate, (Predicate)supplier.get());
        return this;
    }

    public PredicateBuilder not() {
        this.predicate = this.predicate.not();
        return this;
    }

    public PredicateBuilder ifTrueThenAnd(Boolean condition, Supplier<Predicate> supplier) {
        return condition != null && condition ? this.and(supplier) : this;
    }

    public PredicateBuilder ifHasTextThenAnd(String value, Supplier<Predicate> supplier) {
        return this.ifTrueThenAnd(StringUtils.hasText(value), supplier);
    }

    public PredicateBuilder ifNotNullThenAnd(Object value, Supplier<Predicate> supplier) {
        return this.ifTrueThenAnd(value != null, supplier);
    }

    public PredicateBuilder ifNotEmptyThenAnd(Collection values, Supplier<Predicate> supplier) {
        return this.ifTrueThenAnd(!CollectionUtils.isEmpty(values), supplier);
    }

    public <Y extends Comparable<? super Y>> PredicateBuilder ifNotNullThenBetween(Y left, Y right, ComparableExpression<Y> expression) {
        return this.ifNotNullThenAnd(left, () -> {
            return expression.goe(left);
        }).ifNotNullThenAnd(right, () -> {
            return expression.loe(right);
        });
    }

    public PredicateBuilder ensureTrueThenAnd(Boolean condition, Supplier<Predicate> supplier) {
        Assert.isTrue(condition);
        return this.and(supplier);
    }

    public PredicateBuilder ensureHasTextThenAnd(String value, Supplier<Predicate> supplier) {
        return this.ensureTrueThenAnd(StringUtils.hasText(value), supplier);
    }

    public PredicateBuilder ensureNotNullThenAnd(Object value, Supplier<Predicate> supplier) {
        return this.ensureTrueThenAnd(value != null, supplier);
    }

    public PredicateBuilder ensureNotEmptyThenAnd(Collection values, Supplier<Predicate> supplier) {
        return this.ensureTrueThenAnd(!CollectionUtils.isEmpty(values), supplier);
    }

    public Predicate get() {
        return this.predicate;
    }
}
